package com.marvels.common.utils;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.ServletRequest;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSONObject;
import com.marvels.common.constants.ResponseData;
import com.marvels.financial.utils.HttpFormParameter;
import com.marvels.financial.utils.HttpMethod;
import com.marvels.financial.utils.HttpSendModel;



/**
 *
* @ClassName: HttpHelper
* @Description:http帮助类
* @author 李瑶
* @date 2018年1月17日 下午3:48:47
*
 */
public class HttpUtils {

	private static final String APPLICATION_JSON = "application/json";

    /**
     * 获取请求Body
     * @param request
     * @return
     */
    public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
        	MarvelsLogUtil.getInstance().error("getBodyString出现问题！");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                	MarvelsLogUtil.getInstance().error("inputStream关闭异常");
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                	MarvelsLogUtil.getInstance().error("reader关闭异常");
                }
            }
        }
        return sb.toString();
    }

    public static String getGETParam(ServletRequest request) {
    	String param="";
    	JSONObject json = new JSONObject();
		Map paramget = request.getParameterMap();
		if(paramget!=null){
			for(String key:(java.util.Set<String>)paramget.keySet()){
				String[] values= (String[])paramget.get(key);
				String value = "";
				if(values.length==0){

				}else if(values.length==1){
					value = request.getParameter(key);
					json.put(key, value);
				}
			}
		}
		return json.toString();
	}

    public static void main(String[] args) {
		String url  = "http://jifen.cnzhmd.com/index.php?s=/Home/Baimi/adduser";
		long ctime = new Date().getTime()/1000;
		String appid="123";

		String secret = appid+ctime;
		secret = MD5Utils.getMD5(secret);
		secret = MD5Utils.getMD5(secret.substring(0, 16));

		String result = sendPost(url, "phone=13811111111&sourceID=1&appid="+appid+"&ctime="+ctime+"&secret="+secret);
		System.out.println(result);
	}

    /**
	 * 宝付TLSv1.1，TLSv1.2 请求
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public static String baoFuHttpRequest(String url) throws Exception {
		HttpClient httpClient = new DefaultHttpClient();
		HttpGet httpGet = new HttpGet(url);
		httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 6000);
		StringBuilder result = new StringBuilder();
		httpGet.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);
		if (url.startsWith("https://")) {
			try {
				SSLContext ctx = SSLContext.getInstance("TLSv1.2");
				X509TrustManager tm = new X509TrustManager() {
					@Override
					public void checkClientTrusted(X509Certificate[] chain, String authType)
							throws CertificateException {
					}
					@Override
					public void checkServerTrusted(X509Certificate[] chain, String authType)
							throws CertificateException {
					}
					@Override
					public X509Certificate[] getAcceptedIssuers() {
						return null;
					}
				};
				ctx.init(null, new TrustManager[] { tm }, null);
				SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
				ClientConnectionManager ccm = httpClient.getConnectionManager();
				SchemeRegistry sr = ccm.getSchemeRegistry();
				sr.register(new Scheme("https", 443, ssf));
			} catch (Exception e) {
				MarvelsLogUtil.getInstance().error(">>>>>>>>宝付TLSv1.1，TLSv1.2请求异常:",e);
			}
		}
		HttpResponse response = httpClient.execute(httpGet);
		if (response.getStatusLine().getStatusCode() == 200) {
			HttpEntity entity = response.getEntity();
			BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
			String str;
			while ((str = reader.readLine()) != null) {
				result.append(str);
			}
		}

		return result.toString();
	}

	public static ResponseData http_post_body_json(String url,Map<String,Object> param,Header[] req_headers){
		ResponseData responseData = new ResponseData();
		CloseableHttpClient client = HttpClients.createDefault();
		HttpPost post = new HttpPost(url);
		post.addHeader("Content-Type", "application/json");
		post.addHeader("Accept", "application/json");

		if(req_headers!=null){
			for (Header header : req_headers) {
				post.addHeader(header);
			}
		}

		try {
			String json=JSONObject.toJSONString(param).toString();
			MarvelsLogUtil.getInstance().info("http post json===>>"+json);
			StringEntity entity=new StringEntity(json, ContentType.create("application/json", "utf-8"));
			post.setEntity(entity);
			CloseableHttpResponse resp = client.execute(post);
			int sc = resp.getStatusLine().getStatusCode();
			if(sc>=200&&sc<300){
				responseData.setBody(EntityUtils.toString(resp.getEntity()));
			}else{
				responseData.setError(sc+"");
				MarvelsLogUtil.getInstance().info(sc+"");
			}
			Header[] headers =resp.getAllHeaders();
			responseData.setHeaders(headers);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("url————http请求异常", e);
			responseData.setError(e.getMessage());
		}
		return responseData;
	}
	public static ResponseData http_post_body_json(String url,String param,Header[] req_headers){
		ResponseData responseData = new ResponseData();
		CloseableHttpClient client = HttpClients.createDefault();
		HttpPost post = new HttpPost(url);
		post.addHeader("Content-Type", "application/json");
		post.addHeader("Accept", "application/json");

		if(req_headers!=null){
			for (Header header : req_headers) {
				post.addHeader(header);
			}
		}

		try {
			String json=param;
			MarvelsLogUtil.getInstance().info("http post json===>>"+json);
			StringEntity entity=new StringEntity(json, ContentType.create("application/json", "utf-8"));
			post.setEntity(entity);
			CloseableHttpResponse resp = client.execute(post);
			int sc = resp.getStatusLine().getStatusCode();
			if(sc>=200&&sc<300){
				responseData.setBody(EntityUtils.toString(resp.getEntity()));
			}else{
				responseData.setError(sc+"");
				MarvelsLogUtil.getInstance().info(sc+"");
			}
			Header[] headers =resp.getAllHeaders();
			responseData.setHeaders(headers);
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("url————http请求异常", e);
			responseData.setError(e.getMessage(),e);
		}
		return responseData;
	}

	 public static String sendHttpPost(String httpUrl, Map<String, Object> maps) throws Exception{
	        BufferedReader reader=null;
	        StringBuilder result = new StringBuilder();
		 	try{
	        	HttpPost httpPost = new HttpPost(httpUrl);
		        // 创建参数队列
		        List<NameValuePair> nameValuePairs = new ArrayList<>();
		        for (String key : maps.keySet()) {
		            nameValuePairs.add(new BasicNameValuePair(key, String.valueOf(maps.get(key))));
		        }
		        try {
		            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
		        } catch (Exception e) {
		        	MarvelsLogUtil.getInstance().error(">>>>>>sendHttpPost>>>>setEntity" + httpPost.getURI(), e);
		        }
		        HttpClient httpClient = new DefaultHttpClient();
		        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000).build();//设置请求和传输超时时间
		        httpPost.setConfig(requestConfig);
		        HttpResponse response = httpClient.execute(httpPost);
				if (response.getStatusLine().getStatusCode() == 200) {
					HttpEntity entity = response.getEntity();
					reader =  new BufferedReader(
							new InputStreamReader(entity.getContent(), Charset.forName("UTF-8")));
					String string = "";
					while ((string = reader.readLine()) != null) {
						result.append(string);
					}
				}
			}catch (Exception e) {
				MarvelsLogUtil.getInstance().error("发送http Post请求异常==>>",e);
				throw e;
			}finally {
				if(reader != null) reader.close();
			}
			return result.toString();
	    }


	/**
	 * 通过腾讯云发送短信专用
	 * @param url
	 * @param data
	 * @return
	 */
	public static ResponseData sendMsg(String url,JSONObject data) {
		ResponseData responseData = new ResponseData();
        try {
            URL object = new URL(url);
            HttpURLConnection con = (HttpURLConnection) object.openConnection();
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setRequestProperty("Content-Type", "application/json");
            con.setRequestProperty("Accept", "application/json");
            con.setRequestMethod("POST");
            OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream(), "utf-8");
            wr.write(data.toString());
            wr.flush();

            // 显示 POST 请求返回的内容
            StringBuilder sb = new StringBuilder();
            int HttpResult = con.getResponseCode();
            if (HttpResult == HttpURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
                String line = null;
                while ((line = br.readLine()) != null) {
                    sb.append(line + "\n");
                }
                br.close();
                responseData.setBody(sb.toString());
                return responseData;
            } else {
            	responseData.setError(con.getResponseMessage());
                return responseData;
            }
        } catch (Exception e) {
        	MarvelsLogUtil.getInstance().error("通过腾讯云发送短信异常", e);
            return null;
        }
    }
	/**
	 * http请求仅供融云专用
	 * @param appKey
	 * @param appSecret
	 * @param uri
	 * @param contentType
	 * @return
	 * @throws MalformedURLException
	 * @throws IOException
	 * @throws ProtocolException
	 */
	public static HttpURLConnection createPostHttpConnection(String appKey, String appSecret, String uri,
			String contentType) throws MalformedURLException, IOException, ProtocolException {
		String nonce = String.valueOf(Math.random() * 1000000);
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		StringBuilder toSign = new StringBuilder(appSecret).append(nonce).append(timestamp);
		String sign = ShaUtils.hexSHA1(toSign.toString());
		URL url = new URL(uri);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setUseCaches(false);
		conn.setDoInput(true);
		conn.setDoOutput(true);
		conn.setRequestMethod("POST");
		conn.setInstanceFollowRedirects(true);
		conn.setConnectTimeout(30000);
		conn.setReadTimeout(30000);

		conn.setRequestProperty("RC-App-Key", appKey);
		conn.setRequestProperty("RC-Nonce", nonce);
		conn.setRequestProperty("RC-Timestamp", timestamp);
		conn.setRequestProperty("RC-Signature", sign);
		conn.setRequestProperty("Content-Type", contentType);
		return conn;
	}
	// 设置body体
	public static void setBodyParameter(String sb, HttpURLConnection conn) throws IOException {
		DataOutputStream out = new DataOutputStream(conn.getOutputStream());
		out.writeBytes(sb);
		out.flush();
		out.close();
	}
	public static byte[] readInputStream(InputStream inStream) throws Exception {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		while ((len = inStream.read(buffer)) != -1) {
			outStream.write(buffer, 0, len);
		}
		byte[] data = outStream.toByteArray();
		outStream.close();
		inStream.close();
		return data;
	}
	public static String returnResult(HttpURLConnection conn) throws Exception, IOException {
		InputStream input = null;
		if (conn.getResponseCode() == 200) {
			input = conn.getInputStream();
		} else {
			input = conn.getErrorStream();
		}
		String result = new String(readInputStream(input), "UTF-8");
		return result;
	}

	 /**
     * 向指定URL发送GET方法的请求
     *
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error("发送GET请求出现异常", e);
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
            	MarvelsLogUtil.getInstance().error("in流关闭异常", e2);
            }
        }
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            MarvelsLogUtil.getInstance().error("发送 POST 请求出现异常", e);
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
            	MarvelsLogUtil.getInstance().error("流关闭异常", ex);
            }
        }
        return result;
    }

    /**
     * 蜂巢人民银行征信查询专用get请求
     * @param url 路径
     * @return
     * @throws Exception
     */
    public static String honeycombGet(com.alibaba.fastjson.JSONObject jsonObject,String url,String clientId,String key,String service) throws Exception{
    	 String params =jsonObject.toString();
    	 String queryterms=null;
    	 byte[] bytes = EncryptionUtil.encryptByPublicKey(params.getBytes("UTF-8"), key);
    	 queryterms = Base64.encodeBase64String(bytes);
 		//URLEncoder 注意 UTF-8 格式
    	 queryterms = URLEncoder.encode(queryterms,"UTF-8");
 	    //构建请求参数
 	    String urlParam = "service="+service+"&clientId="+clientId + "&queryterms="+ queryterms;
 	    //service=pbccrc
        //get请求返回结果
        try {
        	String urlNameString = url + "?" + urlParam;
            DefaultHttpClient client = new DefaultHttpClient();
            //发送get请求
            HttpGet request = new HttpGet(urlNameString);
            HttpResponse response = client.execute(request);

            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
               return EntityUtils.toString(response.getEntity());
            }
		  }catch (Exception e) {
			MarvelsLogUtil.getInstance().error("honeycombGet==>>",e);
		  }
        return null;
      }
    /**
	 * 使用HttpClient发送post请求
	 *
	 * @param url
	 * @param jsonStr
	 * @return
	 * @throws Exception
	 */
	public static String httpPost(String url, String jsonStr) throws  Exception {
		MarvelsLogUtil.getInstance().info(">>>>>发送http Post请求参数==>>"+jsonStr);
		StringBuilder result = new StringBuilder();
		BufferedReader reader = null;
		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost();
			httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 6000);
			httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
			StringEntity se = new StringEntity(jsonStr, Charset.forName("UTF-8"));
			se.setContentType("text/json");
			httpPost.setEntity(se);
			httpPost.setURI(new URI(url));
			HttpResponse response = httpClient.execute(httpPost);
			if (response.getStatusLine().getStatusCode() == 200) {
				HttpEntity entity = response.getEntity();
				reader =  new BufferedReader(
						new InputStreamReader(entity.getContent(), Charset.forName("UTF-8")));
				String string = "";
				while ((string = reader.readLine()) != null) {
					result.append(string);
				}
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error("发送http Post请求异常==>>",e);
		}finally {
			if(reader != null) reader.close();
		}
		return result.toString();
	}

	public static String RequestForm(String Url,Map<String,String> Parms) throws Exception{
		if(Parms.isEmpty()){
			return  "参数不能为空！";
		}
		String PostParms = "";
		int PostItemTotal = Parms.keySet().size();
		int Itemp=0;
		for (String key : Parms.keySet()){
			PostParms += key + "="+Parms.get(key);
			Itemp++;
			if(Itemp<PostItemTotal){
				PostParms +="&";
			}
		}
		MarvelsLogUtil.getInstance().info("【请求全部参数】："+Url+"?"+PostParms);
		HttpSendModel httpSendModel = new HttpSendModel(Url + "?" + PostParms);
		httpSendModel.setMethod(HttpMethod.POST);
		SimpleHttpResponse response = null;
//		SSLContext sslContext = null; //这边指定tls版本
//		sslContext = SSLContext.getInstance("TLSv1");
//
//		sslContext.init(null, null,null);
		response = doRequest(httpSendModel, "utf-8");
		return response.getEntityString();

	}

	public static SimpleHttpResponse doRequest(HttpSendModel httpSendModel,
			String getCharSet) throws Exception {

		// 创建默认的httpClient客户端端
		SimpleHttpClient simpleHttpclient = new SimpleHttpClient();

		try {
			return doRequest(simpleHttpclient, httpSendModel, getCharSet);
		} finally {
			simpleHttpclient.getHttpclient().getConnectionManager().shutdown();
		}

	}



	/**
	 * @param httpclient
	 * @param httpSendModel
	 * @param getCharSet
	 * @return
	 * @throws Exception
	 */
	public static SimpleHttpResponse doRequest(
			SimpleHttpClient simpleHttpclient, HttpSendModel httpSendModel,
			String getCharSet) throws Exception {

		HttpRequestBase httpRequest = buildHttpRequest(httpSendModel);

		if (httpSendModel.getUrl().startsWith("https://")) {
			simpleHttpclient.enableSSL();
		}

		try {
			System.setProperty("https.protocols", "TLSv1.2");
			HttpResponse response = simpleHttpclient.getHttpclient().execute(
					httpRequest);
			int statusCode = response.getStatusLine().getStatusCode();

			if (SimpleHttpResponse.isRequestSuccess(statusCode)) {
				return new SimpleHttpResponse(statusCode, EntityUtils.toString(
						response.getEntity(), getCharSet), null);
			} else {
				return new SimpleHttpResponse(statusCode, null, response
						.getStatusLine().getReasonPhrase());
			}

		} catch (Exception e) {
//			MarvelsLogUtil.getInstance().error("http请求异常",e);
			throw new Exception("http请求异常："+e.getMessage(), e);
		}

	}


	/**
	 * @param httpSendModel
	 * @return
	 * @throws Exception
	 */
	protected static HttpRequestBase buildHttpRequest(
			HttpSendModel httpSendModel) throws Exception {
		HttpRequestBase httpRequest;
		if (httpSendModel.getMethod() == null) {
			throw new Exception("请求方式未设定");
		} else if (httpSendModel.getMethod() == HttpMethod.POST) {

			String url = httpSendModel.getUrl();
			String sendCharSet = httpSendModel.getCharSet();
			List<HttpFormParameter> params = httpSendModel.getParams();
			List<NameValuePair> qparams = new ArrayList<NameValuePair>();
			if (params != null && params.size() != 0) {

				for (HttpFormParameter param : params) {
					qparams.add(new BasicNameValuePair(param.getName(), param
							.getValue()));
				}

			}

			HttpPost httppost = new HttpPost(url);
			try {
				httppost.setEntity(new UrlEncodedFormEntity(qparams,
						sendCharSet));
			} catch (UnsupportedEncodingException e) {
				throw new Exception("构建post请求参数失败", e);
			}

			httpRequest = httppost;
		} else if (httpSendModel.getMethod() == HttpMethod.GET) {
			HttpGet httpget = new HttpGet(httpSendModel.buildGetRequestUrl());

			httpRequest = httpget;
		} else {
			throw new Exception("请求方式不支持：" + httpSendModel.getMethod());
		}

		return httpRequest;
	}
}
